package q497_RandomPoint;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Solution {
    Random random;
    List<Integer> arr;
    int[][] rects;

    /*
    此题的核心在于 我们要在所有的 点 里面找一个随机的点
    而不是随机挑一个矩形然后在里面选择点 这样会因为矩形之间的某一轴可能存在重叠的区间
    从而导致实际上没有达到随机选取的效果
    这里就需要使用前缀和的方式在一个list里面存储矩形的点
    首先一个矩形的所有整数点的个数有(rect[2] - rect[0] + 1) * (rect[3] - rect[1] + 1)个
    那么我们假设分别有 9 12 16个点的矩形 那么用前缀和存储就是 0 9 21 37
    我们在nextInt(37)中找出一个数 然后用二分查找出来它应该属于哪一个矩形
    然后再对应出它应该属于的点是哪一个即可
     */

    public Solution(int[][] rects) {
        this.rects = rects;
        random = new Random();
        arr = new ArrayList<>();
        arr.add(0);
        for (int[] rect : rects) {
            arr.add(arr.get(arr.size() - 1) + (rect[2] - rect[0] + 1) * (rect[3] - rect[1] + 1));
        }
    }

    public int[] pick() {
        int randomSelect = random.nextInt(arr.get(arr.size() - 1)) + 1;
        int rectIndex = binarySearch(arr, randomSelect) - 1;
        randomSelect = randomSelect - arr.get(rectIndex) - 1;
        int[] rect = rects[rectIndex];
        int a = rect[0], b = rect[1], y = rect[3];
        int col = y - b + 1;
        int da = randomSelect / col;
        int db = randomSelect - col * da;
        return new int[]{a + da, b + db};
    }

    private int binarySearch(List<Integer> arr, int target) {
        int low = 0, high = arr.size() - 1;
        while (low <= high) {
            int mid = (high - low) / 2 + low;
            int num = arr.get(mid);
            if (num == target) {
                return mid;
            } else if (num > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return low;
    }
}

